{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 用于文本到 SQL 的智能体，带有自动错误修正功能  \n",
    "_作者：[Aymeric Roucher](https://huggingface.co/m-ric)_\n",
    "\n",
    "在本教程中，我们将学习如何实现一个利用 SQL 的智能体，使用 `transformers.agents`。\n",
    "\n",
    "与标准文本到 SQL pipeline 相比，**它有什么优势？**\n",
    "\n",
    "标准的文本到 SQL pipeline 是脆弱的，因为生成的 SQL 查询可能是错误的。更糟糕的是，查询可能是错误的，但并不会引发错误，而是返回一些错误的/无用的输出，且不会发出警报。\n",
    "\n",
    "👉 相比之下，**智能体系统能够批判性地检查输出，并决定是否需要更改查询**，从而大大提高其性能。\n",
    "\n",
    "让我们开始构建这个智能体吧！💪"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 设置 SQL 表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sqlalchemy import (\n",
    "    create_engine,\n",
    "    MetaData,\n",
    "    Table,\n",
    "    Column,\n",
    "    String,\n",
    "    Integer,\n",
    "    Float,\n",
    "    insert,\n",
    "    inspect,\n",
    "    text,\n",
    ")\n",
    "\n",
    "engine = create_engine(\"sqlite:///:memory:\")\n",
    "metadata_obj = MetaData()\n",
    "\n",
    "# create city SQL table\n",
    "table_name = \"receipts\"\n",
    "receipts = Table(\n",
    "    table_name,\n",
    "    metadata_obj,\n",
    "    Column(\"receipt_id\", Integer, primary_key=True),\n",
    "    Column(\"customer_name\", String(16), primary_key=True),\n",
    "    Column(\"price\", Float),\n",
    "    Column(\"tip\", Float),\n",
    ")\n",
    "metadata_obj.create_all(engine)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "rows = [\n",
    "    {\"receipt_id\": 1, \"customer_name\": \"Alan Payne\", \"price\": 12.06, \"tip\": 1.20},\n",
    "    {\"receipt_id\": 2, \"customer_name\": \"Alex Mason\", \"price\": 23.86, \"tip\": 0.24},\n",
    "    {\"receipt_id\": 3, \"customer_name\": \"Woodrow Wilson\", \"price\": 53.43, \"tip\": 5.43},\n",
    "    {\"receipt_id\": 4, \"customer_name\": \"Margaret James\", \"price\": 21.11, \"tip\": 1.00},\n",
    "]\n",
    "for row in rows:\n",
    "    stmt = insert(receipts).values(**row)\n",
    "    with engine.begin() as connection:\n",
    "        cursor = connection.execute(stmt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "让我们检查系统是否能通过一个基本查询正常工作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 'Alan Payne', 12.06, 1.2)\n",
      "(2, 'Alex Mason', 23.86, 0.24)\n",
      "(3, 'Woodrow Wilson', 53.43, 5.43)\n",
      "(4, 'Margaret James', 21.11, 1.0)\n"
     ]
    }
   ],
   "source": [
    "with engine.connect() as con:\n",
    "    rows = con.execute(text(\"\"\"SELECT * from receipts\"\"\"))\n",
    "    for row in rows:\n",
    "        print(row)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 构建我们的智能体\n",
    "\n",
    "现在，让我们将 SQL 表格使其可由智能体（工具）检索。\n",
    "\n",
    "智能体的 `description` 属性将被嵌入到大语言模型（LLM）的提示中，这样它就能了解如何使用这个工具。在这个步骤中，我们需要描述 SQL 表格的结构，以便让智能体能够正确地执行查询并与数据库交互。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Columns:\n",
      "  - receipt_id: INTEGER\n",
      "  - customer_name: VARCHAR(16)\n",
      "  - price: FLOAT\n",
      "  - tip: FLOAT\n"
     ]
    }
   ],
   "source": [
    "inspector = inspect(engine)\n",
    "columns_info = [(col[\"name\"], col[\"type\"]) for col in inspector.get_columns(\"receipts\")]\n",
    "\n",
    "table_description = \"Columns:\\n\" + \"\\n\".join(\n",
    "    [f\"  - {name}: {col_type}\" for name, col_type in columns_info]\n",
    ")\n",
    "print(table_description)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在，让我们构建我们的工具。它需要以下内容：（详细信息请参阅[文档](https://huggingface.co/docs/transformers/en/agents#create-a-new-tool)）\n",
    "\n",
    "- 带有 `Args:` 部分的文档字符串\n",
    "- 类型提示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers.agents import tool\n",
    "\n",
    "\n",
    "@tool\n",
    "def sql_engine(query: str) -> str:\n",
    "    \"\"\"\n",
    "    Allows you to perform SQL queries on the table. Returns a string representation of the result.\n",
    "    The table is named 'receipts'. Its description is as follows:\n",
    "        Columns:\n",
    "        - receipt_id: INTEGER\n",
    "        - customer_name: VARCHAR(16)\n",
    "        - price: FLOAT\n",
    "        - tip: FLOAT\n",
    "\n",
    "    Args:\n",
    "        query: The query to perform. This should be correct SQL.\n",
    "    \"\"\"\n",
    "    output = \"\"\n",
    "    with engine.connect() as con:\n",
    "        rows = con.execute(text(query))\n",
    "        for row in rows:\n",
    "            output += \"\\n\" + str(row)\n",
    "    return output"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在让我们创建一个利用这个工具的智能体。\n",
    "\n",
    "我们将使用 `ReactCodeAgent`，它是 `transformers.agents` 的主要智能体类：一个根据 ReAct 框架编写代码并能迭代先前输出的智能体。\n",
    "\n",
    "`llm_engine` 是驱动智能体系统的 LLM。`HfEngine` 允许你通过 HF 的推理 API 调用 LLM，无论是通过无服务器或专用端点，但你也可以使用任何专有的 API：查看[这个指南](agent_change_llm)以了解如何进行适配。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers.agents import ReactCodeAgent, HfApiEngine\n",
    "\n",
    "agent = ReactCodeAgent(\n",
    "    tools=[sql_engine],\n",
    "    llm_engine=HfApiEngine(\"meta-llama/Meta-Llama-3-8B-Instruct\"),\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[32;20;1m======== New task ========\u001b[0m\n",
      "\u001b[37;1mCan you give me the name of the client who got the most expensive receipt?\u001b[0m\n",
      "\u001b[33;1m=== Agent thoughts:\u001b[0m\n",
      "\u001b[0mThought: I will use the tool sql_engine to query the table'receipts' and retrieve the client who got the most expensive receipt. I will sort the results in descending order based on the 'price' column and then return the client name.\u001b[0m\n",
      "\u001b[33;1m>>> Agent is executing the code below:\u001b[0m\n",
      "\u001b[0m\u001b[38;5;7mreceipts_result\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7msql_engine\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mquery\u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144mSELECT customer_name, MAX(price) FROM receipts\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\u001b[38;5;109mprint\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mreceipts_result\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[0m\n",
      "\u001b[33;1m====\u001b[0m\n",
      "\u001b[33;1mPrint outputs:\u001b[0m\n",
      "\u001b[32;20m\n",
      "('Woodrow Wilson', 53.43)\n",
      "\u001b[0m\n",
      "\u001b[33;1m=== Agent thoughts:\u001b[0m\n",
      "\u001b[0mThought: From the output of the previous step, I can see that Woodrow Wilson got the most expensive receipt with a price of 53.43. Now, I want to verify the client name with the receipt data. I will use the tool sql_engine again to query the table'receipts' and retrieve the receipt information for Woodrow Wilson.\u001b[0m\n",
      "\u001b[33;1m>>> Agent is executing the code below:\u001b[0m\n",
      "\u001b[0m\u001b[38;5;7mreceipt_info\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7msql_engine\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mquery\u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144mSELECT * FROM receipts WHERE customer_name=\u001b[39m\u001b[38;5;144m'\u001b[39m\u001b[38;5;144mWoodrow Wilson\u001b[39m\u001b[38;5;144m'\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\u001b[38;5;109mprint\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mreceipt_info\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[0m\n",
      "\u001b[33;1m====\u001b[0m\n",
      "\u001b[33;1mPrint outputs:\u001b[0m\n",
      "\u001b[32;20m\n",
      "(3, 'Woodrow Wilson', 53.43, 5.43)\n",
      "\u001b[0m\n",
      "\u001b[33;1m=== Agent thoughts:\u001b[0m\n",
      "\u001b[0mThought: From the output of the previous step, I can see that the receipt for Woodrow Wilson has the receipt_id 3, the customer_name 'Woodrow Wilson', the price 53.43, and the tip 5.43. Now, I want to give the final answer of the task using the tool final_answer.\u001b[0m\n",
      "\u001b[33;1m>>> Agent is executing the code below:\u001b[0m\n",
      "\u001b[0m\u001b[38;5;7mfinal_answer\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144mThe client who got the most expensive receipt is Woodrow Wilson.\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[0m\n",
      "\u001b[33;1m====\u001b[0m\n",
      "\u001b[33;1mPrint outputs:\u001b[0m\n",
      "\u001b[32;20m\u001b[0m\n",
      "\u001b[33;1mLast output from code snippet:\u001b[0m\n",
      "\u001b[32;20mThe client who got the most expensive receipt is Woodrow Wilson.\u001b[0m\n",
      "\u001b[32;20;1mFinal answer:\u001b[0m\n",
      "\u001b[32;20mThe client who got the most expensive receipt is Woodrow Wilson.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'The client who got the most expensive receipt is Woodrow Wilson.'"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent.run(\"Can you give me the name of the client who got the most expensive receipt?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 提高难度：表格连接\n",
    "\n",
    "现在让我们增加一点难度！我们希望智能体能够处理跨多个表的连接查询。\n",
    "\n",
    "因此，让我们创建一个第二个表，用于记录每个 `receipt_id` 对应的服务员姓名！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "table_name = \"waiters\"\n",
    "receipts = Table(\n",
    "    table_name,\n",
    "    metadata_obj,\n",
    "    Column(\"receipt_id\", Integer, primary_key=True),\n",
    "    Column(\"waiter_name\", String(16), primary_key=True),\n",
    ")\n",
    "metadata_obj.create_all(engine)\n",
    "\n",
    "rows = [\n",
    "    {\"receipt_id\": 1, \"waiter_name\": \"Corey Johnson\"},\n",
    "    {\"receipt_id\": 2, \"waiter_name\": \"Michael Watts\"},\n",
    "    {\"receipt_id\": 3, \"waiter_name\": \"Michael Watts\"},\n",
    "    {\"receipt_id\": 4, \"waiter_name\": \"Margaret James\"},\n",
    "]\n",
    "for row in rows:\n",
    "    stmt = insert(receipts).values(**row)\n",
    "    with engine.begin() as connection:\n",
    "        cursor = connection.execute(stmt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们需要更新 `SQLExecutorTool`，将这个表的描述添加进去，以便让 LLM 能够正确地利用这个表中的信息。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Allows you to perform SQL queries on the table. Beware that this tool's output is a string representation of the execution output.\n",
      "It can use the following tables:\n",
      "\n",
      "Table 'receipts':\n",
      "Columns:\n",
      "  - receipt_id: INTEGER\n",
      "  - customer_name: VARCHAR(16)\n",
      "  - price: FLOAT\n",
      "  - tip: FLOAT\n",
      "\n",
      "Table 'waiters':\n",
      "Columns:\n",
      "  - receipt_id: INTEGER\n",
      "  - waiter_name: VARCHAR(16)\n"
     ]
    }
   ],
   "source": [
    "updated_description = \"\"\"Allows you to perform SQL queries on the table. Beware that this tool's output is a string representation of the execution output.\n",
    "It can use the following tables:\"\"\"\n",
    "\n",
    "inspector = inspect(engine)\n",
    "for table in [\"receipts\", \"waiters\"]:\n",
    "    columns_info = [(col[\"name\"], col[\"type\"]) for col in inspector.get_columns(table)]\n",
    "\n",
    "    table_description = f\"Table '{table}':\\n\"\n",
    "\n",
    "    table_description += \"Columns:\\n\" + \"\\n\".join(\n",
    "        [f\"  - {name}: {col_type}\" for name, col_type in columns_info]\n",
    "    )\n",
    "    updated_description += \"\\n\\n\" + table_description\n",
    "\n",
    "print(updated_description)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由于这个请求比之前的更具挑战性，我们将切换 LLM 引擎，使用更强大的 [Qwen/Qwen2.5-72B-Instruct](https://huggingface.co/Qwen/Qwen2.5-72B-Instruct)！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[32;20;1m======== New task ========\u001b[0m\n",
      "\u001b[37;1mWhich waiter got more total money from tips?\u001b[0m\n",
      "\u001b[33;1m=== Agent thoughts:\u001b[0m\n",
      "\u001b[0mThought: I need to first compute the total amount of tips for each waiter. I will use the `sql_engine` tool to perform a query that sums the tips for each waiter.\u001b[0m\n",
      "\u001b[33;1m>>> Agent is executing the code below:\u001b[0m\n",
      "\u001b[0m\u001b[38;5;7mquery\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;144m\"\"\"\u001b[39m\n",
      "\u001b[38;5;144mSELECT W.waiter_name, SUM(R.tip) as total_tips\u001b[39m\n",
      "\u001b[38;5;144mFROM receipts R\u001b[39m\n",
      "\u001b[38;5;144mJOIN waiters W ON R.receipt_id = W.receipt_id\u001b[39m\n",
      "\u001b[38;5;144mGROUP BY W.waiter_name\u001b[39m\n",
      "\u001b[38;5;144m\"\"\"\u001b[39m\n",
      "\u001b[38;5;7mresult\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7msql_engine\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mquery\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\u001b[38;5;109mprint\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mresult\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[0m\n",
      "\u001b[33;1m====\u001b[0m\n",
      "\u001b[33;1mPrint outputs:\u001b[0m\n",
      "\u001b[32;20m\n",
      "('Corey Johnson', 1.2)\n",
      "('Margaret James', 1.0)\n",
      "('Michael Watts', 5.67)\n",
      "\u001b[0m\n",
      "\u001b[33;1m=== Agent thoughts:\u001b[0m\n",
      "\u001b[0mThought: Now I have the total tips for each waiter. I need to compare these values to find the waiter with the highest total tips. I will use Python code to do this.\u001b[0m\n",
      "\u001b[33;1m>>> Agent is executing the code below:\u001b[0m\n",
      "\u001b[0m\u001b[38;5;60;03m# Extracting the total tips from the result\u001b[39;00m\n",
      "\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7m{\u001b[39m\u001b[38;5;7mrow\u001b[39m\u001b[38;5;7m[\u001b[39m\u001b[38;5;139m0\u001b[39m\u001b[38;5;7m]\u001b[39m\u001b[38;5;7m:\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mrow\u001b[39m\u001b[38;5;7m[\u001b[39m\u001b[38;5;139m1\u001b[39m\u001b[38;5;7m]\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01mfor\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mrow\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01min\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;109meval\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mresult\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;7m}\u001b[39m\n",
      "\u001b[38;5;109mprint\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\n",
      "\u001b[38;5;60;03m# Finding the waiter with the highest total tips\u001b[39;00m\n",
      "\u001b[38;5;7mbest_waiter\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;109mmax\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;7m,\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mkey\u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mget\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\u001b[38;5;7mfinal_answer\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mbest_waiter\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[0m\n",
      "\u001b[33;1m====\u001b[0m\n",
      "\u001b[31;20mCode execution failed due to the following error:\n",
      "EXECUTION FAILED:\n",
      "Evaluation stopped at line 'waiters_tips = {row[0]: row[1] for row in eval(result)}' because of the following error:\n",
      "It is not permitted to evaluate other functions than the provided tools or functions defined in previous code (tried to execute eval).\u001b[0m\n",
      "Traceback (most recent call last):\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 895, in evaluate_python_code\n",
      "    result = evaluate_ast(node, state, static_tools, custom_tools, authorized_imports)\n",
      "             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 741, in evaluate_ast\n",
      "    return evaluate_assign(expression, state, static_tools, custom_tools)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 322, in evaluate_assign\n",
      "    result = evaluate_ast(assign.value, state, static_tools, custom_tools)\n",
      "             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 825, in evaluate_ast\n",
      "    return evaluate_dictcomp(expression, state, static_tools, custom_tools)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 694, in evaluate_dictcomp\n",
      "    iter_value = evaluate_ast(gen.iter, state, static_tools, custom_tools)\n",
      "                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 746, in evaluate_ast\n",
      "    return evaluate_call(expression, state, static_tools, custom_tools)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 385, in evaluate_call\n",
      "    raise InterpreterError(\n",
      "transformers.agents.python_interpreter.InterpreterError: It is not permitted to evaluate other functions than the provided tools or functions defined in previous code (tried to execute eval).\n",
      "\n",
      "During handling of the above exception, another exception occurred:\n",
      "\n",
      "Traceback (most recent call last):\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/agents.py\", line 1135, in step\n",
      "    result = self.python_evaluator(\n",
      "             ^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 904, in evaluate_python_code\n",
      "    raise InterpreterError(msg)\n",
      "transformers.agents.python_interpreter.InterpreterError: EXECUTION FAILED:\n",
      "Evaluation stopped at line 'waiters_tips = {row[0]: row[1] for row in eval(result)}' because of the following error:\n",
      "It is not permitted to evaluate other functions than the provided tools or functions defined in previous code (tried to execute eval).\n",
      "\n",
      "During handling of the above exception, another exception occurred:\n",
      "\n",
      "Traceback (most recent call last):\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/agents.py\", line 811, in direct_run\n",
      "    step_logs = self.step()\n",
      "                ^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/agents.py\", line 1155, in step\n",
      "    raise AgentExecutionError(error_msg)\n",
      "transformers.agents.agents.AgentExecutionError: Code execution failed due to the following error:\n",
      "EXECUTION FAILED:\n",
      "Evaluation stopped at line 'waiters_tips = {row[0]: row[1] for row in eval(result)}' because of the following error:\n",
      "It is not permitted to evaluate other functions than the provided tools or functions defined in previous code (tried to execute eval).\n",
      "\u001b[31;20mError in generating llm output: (ReadTimeoutError(\"HTTPSConnectionPool(host='api-inference.huggingface.co', port=443): Read timed out. (read timeout=120)\"), '(Request ID: a887a819-3b3b-4bab-ba37-a05b83a8cbf1)').\u001b[0m\n",
      "Traceback (most recent call last):\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/urllib3/connectionpool.py\", line 537, in _make_request\n",
      "    response = conn.getresponse()\n",
      "               ^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/urllib3/connection.py\", line 466, in getresponse\n",
      "    httplib_response = super().getresponse()\n",
      "                       ^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/.pyenv/versions/3.12.0/lib/python3.12/http/client.py\", line 1411, in getresponse\n",
      "    response.begin()\n",
      "  File \"/Users/aymeric/.pyenv/versions/3.12.0/lib/python3.12/http/client.py\", line 324, in begin\n",
      "    version, status, reason = self._read_status()\n",
      "                              ^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/.pyenv/versions/3.12.0/lib/python3.12/http/client.py\", line 285, in _read_status\n",
      "    line = str(self.fp.readline(_MAXLINE + 1), \"iso-8859-1\")\n",
      "               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/.pyenv/versions/3.12.0/lib/python3.12/socket.py\", line 707, in readinto\n",
      "    return self._sock.recv_into(b)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/.pyenv/versions/3.12.0/lib/python3.12/ssl.py\", line 1249, in recv_into\n",
      "    return self.read(nbytes, buffer)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/.pyenv/versions/3.12.0/lib/python3.12/ssl.py\", line 1105, in read\n",
      "    return self._sslobj.read(len, buffer)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "TimeoutError: The read operation timed out\n",
      "\n",
      "The above exception was the direct cause of the following exception:\n",
      "\n",
      "Traceback (most recent call last):\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/requests/adapters.py\", line 667, in send\n",
      "    resp = conn.urlopen(\n",
      "           ^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/urllib3/connectionpool.py\", line 847, in urlopen\n",
      "    retries = retries.increment(\n",
      "              ^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/urllib3/util/retry.py\", line 470, in increment\n",
      "    raise reraise(type(error), error, _stacktrace)\n",
      "          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/urllib3/util/util.py\", line 39, in reraise\n",
      "    raise value\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/urllib3/connectionpool.py\", line 793, in urlopen\n",
      "    response = self._make_request(\n",
      "               ^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/urllib3/connectionpool.py\", line 539, in _make_request\n",
      "    self._raise_timeout(err=e, url=url, timeout_value=read_timeout)\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/urllib3/connectionpool.py\", line 370, in _raise_timeout\n",
      "    raise ReadTimeoutError(\n",
      "urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='api-inference.huggingface.co', port=443): Read timed out. (read timeout=120)\n",
      "\n",
      "During handling of the above exception, another exception occurred:\n",
      "\n",
      "Traceback (most recent call last):\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/agents.py\", line 1099, in step\n",
      "    llm_output = self.llm_engine(\n",
      "                 ^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/llm_engine.py\", line 89, in __call__\n",
      "    response = self.client.chat_completion(messages, stop=stop_sequences, max_tokens=1500)\n",
      "               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/huggingface_hub/inference/_client.py\", line 706, in chat_completion\n",
      "    data = self.post(\n",
      "           ^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/huggingface_hub/inference/_client.py\", line 259, in post\n",
      "    response = get_session().post(\n",
      "               ^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/requests/sessions.py\", line 637, in post\n",
      "    return self.request(\"POST\", url, data=data, json=json, **kwargs)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/requests/sessions.py\", line 589, in request\n",
      "    resp = self.send(prep, **send_kwargs)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/requests/sessions.py\", line 703, in send\n",
      "    r = adapter.send(request, **kwargs)\n",
      "        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/huggingface_hub/utils/_http.py\", line 66, in send\n",
      "    return super().send(request, *args, **kwargs)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/venvs/cookbook2/lib/python3.12/site-packages/requests/adapters.py\", line 713, in send\n",
      "    raise ReadTimeout(e, request=request)\n",
      "requests.exceptions.ReadTimeout: (ReadTimeoutError(\"HTTPSConnectionPool(host='api-inference.huggingface.co', port=443): Read timed out. (read timeout=120)\"), '(Request ID: a887a819-3b3b-4bab-ba37-a05b83a8cbf1)')\n",
      "\n",
      "During handling of the above exception, another exception occurred:\n",
      "\n",
      "Traceback (most recent call last):\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/agents.py\", line 811, in direct_run\n",
      "    step_logs = self.step()\n",
      "                ^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/agents.py\", line 1103, in step\n",
      "    raise AgentGenerationError(f\"Error in generating llm output: {e}.\")\n",
      "transformers.agents.agents.AgentGenerationError: Error in generating llm output: (ReadTimeoutError(\"HTTPSConnectionPool(host='api-inference.huggingface.co', port=443): Read timed out. (read timeout=120)\"), '(Request ID: a887a819-3b3b-4bab-ba37-a05b83a8cbf1)').\n",
      "\u001b[33;1m=== Agent thoughts:\u001b[0m\n",
      "\u001b[0mThought: I cannot use `eval` to process the string result. I need to parse the result string in a safer and more direct way. I'll do this by splitting the string and converting it into a dictionary.\u001b[0m\n",
      "\u001b[33;1m>>> Agent is executing the code below:\u001b[0m\n",
      "\u001b[0m\u001b[38;5;60;03m# Parsing the result string into a list of tuples\u001b[39;00m\n",
      "\u001b[38;5;7mresult_list\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7m[\u001b[39m\u001b[38;5;7mline\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7msplit\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144m, \u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01mfor\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mline\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01min\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mresult\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7msplit\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;186m\\n\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;7m]\u001b[39m\n",
      "\n",
      "\u001b[38;5;60;03m# Converting the list of tuples into a dictionary\u001b[39;00m\n",
      "\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7m{\u001b[39m\u001b[38;5;7mrow\u001b[39m\u001b[38;5;7m[\u001b[39m\u001b[38;5;139m0\u001b[39m\u001b[38;5;7m]\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mstrip\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;144m'\u001b[39m\u001b[38;5;186m\\'\u001b[39m\u001b[38;5;144m'\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;7m:\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109mfloat\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mrow\u001b[39m\u001b[38;5;7m[\u001b[39m\u001b[38;5;139m1\u001b[39m\u001b[38;5;7m]\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mstrip\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01mfor\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mrow\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01min\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mresult_list\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01mif\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mrow\u001b[39m\u001b[38;5;7m}\u001b[39m\n",
      "\u001b[38;5;109mprint\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\n",
      "\u001b[38;5;60;03m# Finding the waiter with the highest total tips\u001b[39;00m\n",
      "\u001b[38;5;7mbest_waiter\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;109mmax\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;7m,\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mkey\u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mget\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\u001b[38;5;7mfinal_answer\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mbest_waiter\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[0m\n",
      "\u001b[33;1m====\u001b[0m\n",
      "\u001b[31;20mCode execution failed due to the following error:\n",
      "EXECUTION FAILED:\n",
      "Evaluation stopped at line 'waiters_tips = {row[0].strip('\\''): float(row[1].strip()) for row in result_list if row}' because of the following error:\n",
      "Index 1 out of bounds for list of length 1\u001b[0m\n",
      "Traceback (most recent call last):\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 895, in evaluate_python_code\n",
      "    result = evaluate_ast(node, state, static_tools, custom_tools, authorized_imports)\n",
      "             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 741, in evaluate_ast\n",
      "    return evaluate_assign(expression, state, static_tools, custom_tools)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 322, in evaluate_assign\n",
      "    result = evaluate_ast(assign.value, state, static_tools, custom_tools)\n",
      "             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 825, in evaluate_ast\n",
      "    return evaluate_dictcomp(expression, state, static_tools, custom_tools)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 700, in evaluate_dictcomp\n",
      "    val = evaluate_ast(dictcomp.value, new_state, static_tools, custom_tools)\n",
      "          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 746, in evaluate_ast\n",
      "    return evaluate_call(expression, state, static_tools, custom_tools)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 394, in evaluate_call\n",
      "    args.append(evaluate_ast(arg, state, static_tools, custom_tools))\n",
      "                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 746, in evaluate_ast\n",
      "    return evaluate_call(expression, state, static_tools, custom_tools)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 368, in evaluate_call\n",
      "    obj = evaluate_ast(call.func.value, state, static_tools, custom_tools)\n",
      "          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 804, in evaluate_ast\n",
      "    return evaluate_subscript(expression, state, static_tools, custom_tools)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 460, in evaluate_subscript\n",
      "    raise InterpreterError(f\"Index {index} out of bounds for list of length {len(value)}\")\n",
      "transformers.agents.python_interpreter.InterpreterError: Index 1 out of bounds for list of length 1\n",
      "\n",
      "During handling of the above exception, another exception occurred:\n",
      "\n",
      "Traceback (most recent call last):\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/agents.py\", line 1135, in step\n",
      "    result = self.python_evaluator(\n",
      "             ^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/python_interpreter.py\", line 904, in evaluate_python_code\n",
      "    raise InterpreterError(msg)\n",
      "transformers.agents.python_interpreter.InterpreterError: EXECUTION FAILED:\n",
      "Evaluation stopped at line 'waiters_tips = {row[0].strip('\\''): float(row[1].strip()) for row in result_list if row}' because of the following error:\n",
      "Index 1 out of bounds for list of length 1\n",
      "\n",
      "During handling of the above exception, another exception occurred:\n",
      "\n",
      "Traceback (most recent call last):\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/agents.py\", line 811, in direct_run\n",
      "    step_logs = self.step()\n",
      "                ^^^^^^^^^^^\n",
      "  File \"/Users/aymeric/Documents/Code/original_transformers/transformers/src/transformers/agents/agents.py\", line 1155, in step\n",
      "    raise AgentExecutionError(error_msg)\n",
      "transformers.agents.agents.AgentExecutionError: Code execution failed due to the following error:\n",
      "EXECUTION FAILED:\n",
      "Evaluation stopped at line 'waiters_tips = {row[0].strip('\\''): float(row[1].strip()) for row in result_list if row}' because of the following error:\n",
      "Index 1 out of bounds for list of length 1\n",
      "\u001b[33;1m=== Agent thoughts:\u001b[0m\n",
      "\u001b[0mThought: It appears that the result string is not being processed correctly. I need to ensure that the string is split into a list of tuples in a way that correctly captures each row. I'll inspect the result string to understand its exact format.\u001b[0m\n",
      "\u001b[33;1m>>> Agent is executing the code below:\u001b[0m\n",
      "\u001b[0m\u001b[38;5;60;03m# Inspect the result string\u001b[39;00m\n",
      "\u001b[38;5;109mprint\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mresult\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[0m\n",
      "\u001b[33;1m====\u001b[0m\n",
      "\u001b[33;1mPrint outputs:\u001b[0m\n",
      "\u001b[32;20m\n",
      "('Corey Johnson', 1.2)\n",
      "('Margaret James', 1.0)\n",
      "('Michael Watts', 5.67)\n",
      "\u001b[0m\n",
      "\u001b[33;1m=== Agent thoughts:\u001b[0m\n",
      "\u001b[0mThought: The result string is a list of tuples, but it's not in a format that can be directly parsed using `split`. I need to handle the result string more carefully. I'll use a list comprehension to process the string and extract the waiter names and their total tips.\u001b[0m\n",
      "\u001b[33;1m>>> Agent is executing the code below:\u001b[0m\n",
      "\u001b[0m\u001b[38;5;60;03m# Split the result string into individual lines\u001b[39;00m\n",
      "\u001b[38;5;7mlines\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mresult\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mstrip\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144m[]\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mreplace\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144m)\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m,\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mreplace\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144m(\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m,\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7msplit\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;186m\\n\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\n",
      "\u001b[38;5;60;03m# Process each line to create a dictionary of waiters and their total tips\u001b[39;00m\n",
      "\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7m{\u001b[39m\u001b[38;5;7m}\u001b[39m\n",
      "\u001b[38;5;109;01mfor\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mline\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01min\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mlines\u001b[39m\u001b[38;5;7m:\u001b[39m\n",
      "\u001b[38;5;7m    \u001b[39m\u001b[38;5;109;01mif\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mline\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mstrip\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;7m:\u001b[39m\n",
      "\u001b[38;5;7m        \u001b[39m\u001b[38;5;7mwaiter\u001b[39m\u001b[38;5;7m,\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mtip\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mline\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mstrip\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7msplit\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144m, \u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\u001b[38;5;7m        \u001b[39m\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;7m[\u001b[39m\u001b[38;5;7mwaiter\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mstrip\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mstrip\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;144m'\u001b[39m\u001b[38;5;144m\"\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;7m]\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;109mfloat\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mtip\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mstrip\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\n",
      "\u001b[38;5;109mprint\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\n",
      "\u001b[38;5;60;03m# Finding the waiter with the highest total tips\u001b[39;00m\n",
      "\u001b[38;5;7mbest_waiter\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7m \u001b[39m\u001b[38;5;109mmax\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;7m,\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mkey\u001b[39m\u001b[38;5;109;01m=\u001b[39;00m\u001b[38;5;7mwaiters_tips\u001b[39m\u001b[38;5;109;01m.\u001b[39;00m\u001b[38;5;7mget\u001b[39m\u001b[38;5;7m)\u001b[39m\n",
      "\u001b[38;5;7mfinal_answer\u001b[39m\u001b[38;5;7m(\u001b[39m\u001b[38;5;7mbest_waiter\u001b[39m\u001b[38;5;7m)\u001b[39m\u001b[0m\n",
      "\u001b[33;1m====\u001b[0m\n",
      "\u001b[33;1mPrint outputs:\u001b[0m\n",
      "\u001b[32;20m{'Corey Johnson': 1.2, 'Margaret James': 1.0, 'Michael Watts': 5.67}\n",
      "\u001b[0m\n",
      "\u001b[33;1mLast output from code snippet:\u001b[0m\n",
      "\u001b[32;20mMichael Watts\u001b[0m\n",
      "\u001b[32;20;1mFinal answer:\u001b[0m\n",
      "\u001b[32;20mMichael Watts\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Michael Watts'"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sql_engine.description = updated_description\n",
    "\n",
    "agent = ReactCodeAgent(\n",
    "    tools=[sql_engine],\n",
    "    llm_engine=HfApiEngine(\"Qwen/Qwen2.5-72B-Instruct\"),\n",
    ")\n",
    "\n",
    "agent.run(\"Which waiter got more total money from tips?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "它直接就能工作！设置过程出乎意料地简单，不是吗？\n",
    "\n",
    "✅ 现在你可以去构建你一直梦想的文本到 SQL 系统了！✨"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "cookbook2",
   "language": "python",
   "name": "cookbook2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
